package com.jibei.mendo.utils;

import android.annotation.SuppressLint;
import android.util.Log;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.TimeUnit;

import android_serialport_api.SerialPort;
import io.reactivex.Observable;
import io.reactivex.disposables.Disposable;

/**
 * Created by Devin on 2019/8/10.
 */
public class SerialPortUtil {

    private SerialPort mSerialPort;
    private InputStream mInputStream;
    private OutputStream mOutputStream;
    private boolean isRun;
    private boolean isOpenSuccess;

    private String recinfo_ttS2 = "";
    private boolean isGetBackCommand = true;

    private SerialPortUtil() {
        OpenSerial();
    }

    public static SerialPortUtil getInstance() {
        return SerialPortUtil.Holder.instance;
    }

    private static class Holder {
        private static final SerialPortUtil instance = new SerialPortUtil();
    }

    private void OpenSerial() {
        // 打开
        String prot = "ttyS2";
        int baudrate = 9600;
        try {
            mSerialPort = new SerialPort(new File("/dev/" + prot), baudrate, 0);
            Log.d("lhl", "  串口打开        " + mSerialPort.toString());
            mInputStream = mSerialPort.getInputStream();
            mOutputStream = mSerialPort.getOutputStream();
            isOpenSuccess = true;
        } catch (Exception e) {
            e.printStackTrace();
            isOpenSuccess = false;
        }

    }

    public void serialPortStartRead() {
        if (!isOpenSuccess) {
            Log.e("lhl", "串口   读取数据打开失败");
            return;
        }
        ThreadPoolUtils.execute(() -> {
            // 接收
            isRun = true;
            while (isRun) {
                int size;
                try {
                    byte[] buffer = new byte[1024];
                    if (mInputStream == null) {
                        Thread.sleep(10000);
                        Log.e("lhl", "接收到串口信息:   sleep   10s");
                        OpenSerial();
                        //                        return;
                    } else {
                        mInputStream = mSerialPort.getInputStream();
                    }
                    size = mInputStream.read(buffer);
                    if (size > 0) {
                        recinfo_ttS2 = MyFunc.ByteArrToHex(buffer, 0, size);
                        //                        EventBusUtil.getInstance().postEvent(new Event(Constant.Events.BACK_COMMAND, recinfo));
                        Log.d("lhl", "接收到串口信息:" + recinfo_ttS2);
                    } else {
                        Log.e("lhl", "接收到串口信息:   为空");
                    }
                    Thread.sleep(10);//间隔50ms
                } catch (IOException | InterruptedException e) {
                    Log.e("lhl", "接收到串口信息:异常>>>" + e.getMessage());
                    e.printStackTrace();
                }
            }
        });
    }

    @SuppressLint("CheckResult")
    public void sendSerialPortMsg(String inHex) {
        // 发送
        if (!isOpenSuccess) {
            Log.e("lhl", "串口   发送失败");
            return;
        }
        try {
            if (mSerialPort == null) {
                OpenSerial();//打开串口
                Log.e("lhl", "串口   发送失败");
            } else {
                byte[] bytes = MyFunc.HexToByteArr(inHex);
                mOutputStream.write(bytes);
                Log.i("lhl", "SerialPortUtil   串口  发送成功>>>" + inHex);
            }
        } catch (Exception e) {
            Log.e("lhl", "串口   发送失败");
            e.printStackTrace();
        }
    }

    /**
     * 发送一次命令，返回是否发送成功
     *
     * @param commandStr     需要发送的命令
     * @param commandBackStr 命令的返回
     * @param intervalTime   间隔多久算是失败
     * @return 是否发送成功
     */
    public synchronized boolean sendCommand(String commandStr, String commandBackStr, long intervalTime) {
        isGetBackCommand = true;
        sendSerialPortMsg(commandStr);//发送命令

        Disposable disposable = Observable.timer(intervalTime, TimeUnit.MILLISECONDS)
                .subscribe(aLong -> {
                    isGetBackCommand = false;
                });
        while (isGetBackCommand) {
            if (recinfo_ttS2.equals(commandBackStr)) {
                disposable.dispose();
                return true;
            }
        }
        return false;
    }

    /**
     * 发送一次命令，返回收到的指令
     *
     * @param commandStr 需要发送的命令
     * @param delayTime  延迟多久得到结果
     * @return 命令的返回
     */
    public synchronized String sendCommandWithBackDelay(String commandStr, long delayTime) {
        recinfo_ttS2 = "";
        try {
            sendSerialPortMsg(commandStr);//发送命令
            Thread.sleep(delayTime);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return recinfo_ttS2;
    }

    /**
     * 发送一次命令，返回收到的指令
     *
     * @param commandStr 需要发送的命令
     * @param delayTime  延迟多久发送下一个命令
     * @return 命令的返回
     */
    public synchronized String sendCommandWithBack(String commandStr, long delayTime) {
        recinfo_ttS2 = "";
        try {
            Thread.sleep(delayTime);
            sendSerialPortMsg(commandStr);//发送命令
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return recinfo_ttS2;
    }

    private void closeSerialPort() {
        isRun = false;
        if (mSerialPort != null) {
            try {
                Log.d("lhl", "close serial port");
                mSerialPort.close();
                mSerialPort = null;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (mInputStream != null) {
            try {
                mInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (mOutputStream != null) {
            try {
                mOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
